use crate::sketchbook::ids::{
DatasetId, DynPropertyId, ObservationId, StatPropertyId, UninterpretedFnId, VarId,
};
use crate::sketchbook::model::{Essentiality, Monotonicity};
use crate::sketchbook::properties::dynamic_props::are_same_dyn_variant;
use crate::sketchbook::properties::static_props::{are_same_stat_variant, StatPropertyType};
use crate::sketchbook::properties::{
DynPropIterator, DynProperty, PropertyManager, StatPropIterator, StatProperty,
};
use crate::sketchbook::utils::assert_ids_unique;
use std::collections::HashMap;
use std::str::FromStr;
impl PropertyManager {
pub fn new_empty() -> PropertyManager {
PropertyManager {
dyn_properties: HashMap::new(),
stat_properties: HashMap::new(),
}
}
pub fn new_from_properties(
dyn_properties: Vec<(&str, DynProperty)>,
stat_properties: Vec<(&str, StatProperty)>,
) -> Result<PropertyManager, String> {
let mut manager = PropertyManager::new_empty();
let dyn_prop_ids = dyn_properties.iter().map(|pair| pair.0).collect();
assert_ids_unique(&dyn_prop_ids)?;
let stat_prop_ids = stat_properties.iter().map(|pair| pair.0).collect();
assert_ids_unique(&stat_prop_ids)?;
for (id, prop) in dyn_properties {
manager.dyn_properties.insert(DynPropertyId::new(id)?, prop);
}
for (id, prop) in stat_properties {
manager
.stat_properties
.insert(StatPropertyId::new(id)?, prop);
}
Ok(manager)
}
}
impl PropertyManager {
pub fn add_dynamic(&mut self, id: DynPropertyId, prop: DynProperty) -> Result<(), String> {
self.assert_no_dynamic(&id)?;
self.dyn_properties.insert(id, prop);
Ok(())
}
pub fn add_dynamic_by_str(&mut self, id: &str, prop: DynProperty) -> Result<(), String> {
let id = DynPropertyId::new(id)?;
self.add_dynamic(id, prop)
}
pub fn add_static(&mut self, id: StatPropertyId, prop: StatProperty) -> Result<(), String> {
self.assert_no_static(&id)?;
self.stat_properties.insert(id, prop);
Ok(())
}
pub fn add_static_by_str(&mut self, id: &str, prop: StatProperty) -> Result<(), String> {
let id = StatPropertyId::new(id)?;
self.add_static(id, prop)
}
pub fn set_dyn_name(&mut self, id: &DynPropertyId, new_name: &str) -> Result<(), String> {
self.assert_valid_dynamic(id)?;
let prop = self.dyn_properties.get_mut(id).unwrap();
prop.set_name(new_name)
}
pub fn set_stat_name(&mut self, id: &StatPropertyId, new_name: &str) -> Result<(), String> {
self.assert_valid_static(id)?;
let prop = self.stat_properties.get_mut(id).unwrap();
prop.set_name(new_name)
}
pub fn set_dyn_dataset(
&mut self,
id: &DynPropertyId,
new_dataset: DatasetId,
) -> Result<(), String> {
self.assert_valid_dynamic(id)?;
let prop = self.dyn_properties.get_mut(id).unwrap();
prop.set_dataset(new_dataset)
}
pub fn set_dyn_observation(
&mut self,
id: &DynPropertyId,
new_obs: ObservationId,
) -> Result<(), String> {
self.assert_valid_dynamic(id)?;
let prop = self.dyn_properties.get_mut(id).unwrap();
prop.set_observation(new_obs)
}
pub fn set_dyn_formula(&mut self, id: &DynPropertyId, new_formula: &str) -> Result<(), String> {
self.assert_valid_dynamic(id)?;
let prop = self.dyn_properties.get_mut(id).unwrap();
prop.set_formula(new_formula)
}
pub fn set_dyn_none_observation(&mut self, id: &DynPropertyId) -> Result<(), String> {
self.assert_valid_dynamic(id)?;
let prop = self.dyn_properties.get_mut(id).unwrap();
prop.remove_observation()
}
pub fn set_dyn_attr_count(
&mut self,
id: &DynPropertyId,
minimal: usize,
maximal: usize,
) -> Result<(), String> {
self.assert_valid_dynamic(id)?;
let prop = self.dyn_properties.get_mut(id).unwrap();
prop.set_attr_count(minimal, maximal)
}
pub fn set_dyn_trap_space_details(
&mut self,
id: &DynPropertyId,
is_minimal: bool,
non_percolable: bool,
) -> Result<(), String> {
self.assert_valid_dynamic(id)?;
let prop = self.dyn_properties.get_mut(id).unwrap();
prop.set_trap_space_details(is_minimal, non_percolable)
}
pub fn set_stat_formula(
&mut self,
id: &StatPropertyId,
new_formula: &str,
) -> Result<(), String> {
self.assert_valid_static(id)?;
let prop = self.stat_properties.get_mut(id).unwrap();
prop.set_formula(new_formula)
}
pub fn set_stat_input_var(
&mut self,
id: &StatPropertyId,
new_var: VarId,
) -> Result<(), String> {
self.assert_valid_static(id)?;
let prop = self.stat_properties.get_mut(id).unwrap();
prop.set_input_var(new_var)
}
pub fn set_stat_input_index(
&mut self,
id: &StatPropertyId,
new_idx: usize,
) -> Result<(), String> {
self.assert_valid_static(id)?;
let prop = self.stat_properties.get_mut(id).unwrap();
prop.set_input_index(new_idx)
}
pub fn set_stat_target_fn(
&mut self,
id: &StatPropertyId,
new_target: UninterpretedFnId,
) -> Result<(), String> {
self.assert_valid_static(id)?;
let prop = self.stat_properties.get_mut(id).unwrap();
prop.set_target_fn(new_target)
}
pub fn set_stat_target_var(
&mut self,
id: &StatPropertyId,
new_target: VarId,
) -> Result<(), String> {
self.assert_valid_static(id)?;
let prop = self.stat_properties.get_mut(id).unwrap();
prop.set_target_var(new_target)
}
pub fn set_stat_monotonicity(
&mut self,
id: &StatPropertyId,
monotonicity: Monotonicity,
) -> Result<(), String> {
self.assert_valid_static(id)?;
let prop = self.stat_properties.get_mut(id).unwrap();
prop.set_monotonicity(monotonicity)
}
pub fn set_stat_essentiality(
&mut self,
id: &StatPropertyId,
essentiality: Essentiality,
) -> Result<(), String> {
self.assert_valid_static(id)?;
let prop = self.stat_properties.get_mut(id).unwrap();
prop.set_essentiality(essentiality)
}
pub fn set_stat_context(&mut self, id: &StatPropertyId, context: String) -> Result<(), String> {
self.assert_valid_static(id)?;
let prop = self.stat_properties.get_mut(id).unwrap();
prop.set_context(context)
}
pub fn swap_dyn_content(
&mut self,
id: &DynPropertyId,
new_content: DynProperty,
) -> Result<(), String> {
let orig_content = self.get_dyn_prop(id)?;
if !are_same_dyn_variant(new_content.get_prop_data(), orig_content.get_prop_data()) {
return Err("Variant of the dynamic property cannot change.".to_string());
}
self.dyn_properties.insert(id.clone(), new_content);
Ok(())
}
pub fn swap_dyn_content_by_str(
&mut self,
id: &str,
new_content: DynProperty,
) -> Result<(), String> {
let prop_id = DynPropertyId::new(id)?;
self.swap_dyn_content(&prop_id, new_content)
}
pub fn swap_stat_content(
&mut self,
id: &StatPropertyId,
new_content: StatProperty,
) -> Result<(), String> {
let orig_content = self.get_stat_prop(id)?;
if !are_same_stat_variant(new_content.get_prop_data(), orig_content.get_prop_data()) {
return Err("Variant of the static property cannot change.".to_string());
}
self.stat_properties.insert(id.clone(), new_content);
Ok(())
}
pub fn swap_stat_content_by_str(
&mut self,
id: &str,
new_content: StatProperty,
) -> Result<(), String> {
let prop_id = StatPropertyId::new(id)?;
self.swap_stat_content(&prop_id, new_content)
}
pub fn set_dyn_id(
&mut self,
original_id: &DynPropertyId,
new_id: DynPropertyId,
) -> Result<(), String> {
self.assert_valid_dynamic(original_id)?;
self.assert_no_dynamic(&new_id)?;
if let Some(property) = self.dyn_properties.remove(original_id) {
self.dyn_properties.insert(new_id.clone(), property);
} else {
panic!("Error when modifying dyn property's id in the property map.");
}
Ok(())
}
pub fn set_dyn_id_by_str(&mut self, original_id: &str, new_id: &str) -> Result<(), String> {
let original_id = DynPropertyId::new(original_id)?;
let new_id = DynPropertyId::new(new_id)?;
self.set_dyn_id(&original_id, new_id)
}
pub fn set_stat_id(
&mut self,
original_id: &StatPropertyId,
new_id: StatPropertyId,
) -> Result<(), String> {
self.assert_valid_static(original_id)?;
self.assert_no_static(&new_id)?;
if let Some(property) = self.stat_properties.remove(original_id) {
self.stat_properties.insert(new_id.clone(), property);
} else {
panic!("Error when modifying stat property's id in the property map.");
}
Ok(())
}
pub fn set_stat_id_by_str(&mut self, original_id: &str, new_id: &str) -> Result<(), String> {
let original_id = StatPropertyId::new(original_id)?;
let new_id = StatPropertyId::new(new_id)?;
self.set_stat_id(&original_id, new_id)
}
pub fn remove_dynamic(&mut self, id: &DynPropertyId) -> Result<(), String> {
self.assert_valid_dynamic(id)?;
self.dyn_properties.remove(id).unwrap();
Ok(())
}
pub fn remove_static(&mut self, id: &StatPropertyId) -> Result<(), String> {
self.assert_valid_static(id)?;
self.stat_properties.remove(id).unwrap();
Ok(())
}
pub fn make_generated_reg_prop_ids_consistent(&mut self) {
let mut id_change_list: Vec<(StatPropertyId, StatPropertyId)> = Vec::new();
for (prop_id, prop) in self.stat_properties.iter() {
match prop.get_prop_data() {
StatPropertyType::RegulationEssential(p) => {
let expected_id = StatProperty::get_essentiality_prop_id(
p.input.as_ref().unwrap(),
p.target.as_ref().unwrap(),
);
if prop_id != &expected_id {
id_change_list.push((prop_id.clone(), expected_id.clone()));
}
}
StatPropertyType::RegulationMonotonic(p) => {
let expected_id = StatProperty::get_monotonicity_prop_id(
p.input.as_ref().unwrap(),
p.target.as_ref().unwrap(),
);
if prop_id != &expected_id {
id_change_list.push((prop_id.clone(), expected_id.clone()));
}
}
_ => {}
}
}
for (current_id, new_id) in id_change_list {
self.set_stat_id(¤t_id, new_id).unwrap();
}
}
}
impl PropertyManager {
fn assert_no_dynamic(&self, id: &DynPropertyId) -> Result<(), String> {
if self.is_valid_dyn_property_id(id) {
Err(format!("Dynamic property with id {id} already exists."))
} else {
Ok(())
}
}
fn assert_valid_dynamic(&self, id: &DynPropertyId) -> Result<(), String> {
if self.is_valid_dyn_property_id(id) {
Ok(())
} else {
Err(format!("Dynamic property with id {id} does not exist."))
}
}
fn assert_no_static(&self, id: &StatPropertyId) -> Result<(), String> {
if self.is_valid_stat_property_id(id) {
Err(format!("Static property with id {id} already exists."))
} else {
Ok(())
}
}
fn assert_valid_static(&self, id: &StatPropertyId) -> Result<(), String> {
if self.is_valid_stat_property_id(id) {
Ok(())
} else {
Err(format!("Static property with id {id} does not exist."))
}
}
}
impl PropertyManager {
pub fn num_dyn_properties(&self) -> usize {
self.dyn_properties.len()
}
pub fn num_stat_properties(&self) -> usize {
self.stat_properties.len()
}
pub fn is_valid_dyn_property_id(&self, id: &DynPropertyId) -> bool {
self.dyn_properties.contains_key(id)
}
pub fn is_valid_stat_property_id(&self, id: &StatPropertyId) -> bool {
self.stat_properties.contains_key(id)
}
pub fn dyn_props(&self) -> DynPropIterator {
self.dyn_properties.iter()
}
pub fn stat_props(&self) -> StatPropIterator {
self.stat_properties.iter()
}
pub fn get_dyn_prop_id(&self, id: &str) -> Result<DynPropertyId, String> {
let property_id = DynPropertyId::from_str(id)?;
if self.is_valid_dyn_property_id(&property_id) {
return Ok(property_id);
}
Err(format!("Dynamic property with ID {id} does not exist."))
}
pub fn get_dyn_prop(&self, id: &DynPropertyId) -> Result<&DynProperty, String> {
let dyn_prop = self
.dyn_properties
.get(id)
.ok_or(format!("Dynamic property with ID {id} does not exist."))?;
Ok(dyn_prop)
}
pub fn get_stat_prop_id(&self, id: &str) -> Result<StatPropertyId, String> {
let property_id = StatPropertyId::from_str(id)?;
if self.is_valid_stat_property_id(&property_id) {
return Ok(property_id);
}
Err(format!("Static property with ID {id} does not exist."))
}
pub fn get_stat_prop(&self, id: &StatPropertyId) -> Result<&StatProperty, String> {
let stat_prop = self
.stat_properties
.get(id)
.ok_or(format!("Static property with ID {id} does not exist."))?;
Ok(stat_prop)
}
}